package demo;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: rei
 * Date: 2025-11-06
 * Time: 15:39
 */

//任务的容器
public class MyTimer {
    private BlockingQueue<Task> queue = new PriorityBlockingQueue<>();

    final Object locker = new Object();

    public MyTimer() {
        //初始化计时器的时候,加载一个线程来执行队列里面的任务,一直读取队列中的任务
        Thread t = new Thread(() -> {
            System.out.println("lamb" + this);
            while (true) {
                try {
                    synchronized (locker) {
                        Task task = this.queue.take();
                        //拿出来之后,根据时间来判断是否执行,如果没到时间就放回去
                        if (System.currentTimeMillis() >= task.getTime()) {
                            //这里的run就是一个普通的方法
                            task.getRunnable().run();
                        } else {
                            //如果没到时间就设置一个等待时间,任务执行时间 - 当前时间
                            long waitTime = task.getTime() - System.currentTimeMillis();
                            queue.put(task);


                            locker.wait(waitTime);
                        }
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        t.start();
    }

    //传入任务和时间
    public void schedule(Runnable tk, long delay) throws InterruptedException {
        Task task = new Task(tk, delay);

        //把task放入阻塞队列中 然后要有一个线程来执行队列里面的任务
        //当有新任务放入时,幻想等待的线程
        queue.put(task);
        synchronized (locker) {
            locker.notifyAll();
        }
    }


}

//放任务  runnable 类型 ,时间
class Task implements Comparable<Task> {
    // 任务
    private Runnable runnable;
    // 时间 这里的时间就是要延时的时间
    private long time;

    public Task(Runnable runnable, long delay) {
        //任务校验
        if (runnable == null) {
            throw new IllegalArgumentException("任务不能为空");
        }
        if (delay < 0) {
            throw new IllegalArgumentException("时间不能为负");
        }
        //时间校验
        this.runnable = runnable;
        this.time = System.currentTimeMillis() + delay;
        //           当前系统时间 加上 传入的要延时几秒的时间
    }

    public Runnable getRunnable() {
        return runnable;
    }

    public long getTime() {
        return time;
    }

    public int compareTo(Task o) {
        //要比的就是传入队列里面的task和
        return Long.compare(this.time, o.getTime());
        //  return (int) (this.time - o.getTime());

    }
}